<template>
  <div class="user-dialog">
    <el-dialog v-model="visibleDialog" width="600px" :title="dialogTitle" :append-to-body="true">
      <div class="confirm-body">
        <div class="left">
          <el-input
            v-model="filterText"
            placeholder="搜索"
          >
            <template #prefix>
              <el-icon><i-ep-search /></el-icon>
            </template>
          </el-input>
          <el-tree
            v-if="roleList"
            ref="treeRef"
            :props="treeProps"
            :data="roleList"
            style="margin-top: 5px;"
            node-key="id"
            :filter-node-method="filterNode"
            empty-text="无数据"
            :check-strictly="false"
            @node-click="handleNodeClick"
          />
          <el-tree
            v-else
            ref="treeRef"
            :props="treeProps"
            :data="treeList"
            style="margin-top: 5px;"
            show-checkbox
            node-key="id"
            :filter-node-method="filterNode"
            :default-checked-keys="checkedKeys"
            :default-expanded-keys="checkedKeys"
            empty-text="无数据"
            :check-strictly="checkStrictly"
            @check-change="handleCheckChange"
          />
        </div>
        <div class="right">
          <div class="right-header">
            已选（{{ rightList.length }}）
            <a @click="clear">清空</a>
          </div>
          <div class="right-content">
            <div v-for="(item,index) in rightList" :key="index" class="right-content-item">
              <el-icon class="avatar">
                <i-ep-avatar v-if="item.type===1" />
                <i-ep-share v-else />
              </el-icon>
              <span>{{ item.name }}</span>
              <el-icon class="close" @click="remove(item)"><i-ep-circle-close /></el-icon>
            </div>
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="visibleDialog = false">取 消</el-button>
          <el-button type="primary" @click="saveDialog">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script>
import { ref, computed, watch, nextTick } from 'vue'

export default {
  props: {
    /** 成员列表 */
    treeList: {
      type: Array,
      default: () => [/** {id,type,name,children} */]
    },
    /** 已选中 */
    modelValue: {
      type: Array,
      default: () => []
    },
    /** 是否允许选中部门 */
    checkStrictly: {
      type: Boolean,
      default: false
    },
    /** 角色列表 */
    roleList: {
      type: Array,
      default: null
    },
    visible: {
      type: Boolean,
      default: false
    }
  },
  emits: ['update:modelValue', 'update:visible'],
  setup(props, { emit }) {
    const visibleDialog = computed({
      get() {
        return props.visible
      },
      set(val) {
        emit('update:visible', val)
      }
    })

    const treeRef = ref(null)
    const filterText = ref('')
    const checkedKeys = ref([])
    const rightList = ref([])

    const treeProps = {
      label: 'name',
      children: 'children'
    }

    const dialogTitle = computed(() => {
      if (props.roleList) { return '选择角色' }
      return props.checkStrictly ? '选择人员或部门' : '选择人员'
    })

    watch(visibleDialog, (flag) => {
      if (flag) {
        checkedKeys.value = props.modelValue.map(m => m.id)
        rightList.value = props.modelValue
        nextTick(() => {
          treeRef.value.setCheckedKeys(checkedKeys.value, false) // 更新选中状态
        })
      }
    })

    watch(filterText, (val) => {
      treeRef.value.filter(val)
    })

    /** 搜索过滤 */
    const filterNode = (value, data) => {
      if (!value) return true
      return data[treeProps.label].includes(value)
    }

    /** 更新选中列表数据 */
    const handleCheckChange = (data, checked) => {
      const { id, type, name } = data
      if (checked) {
        if (!props.checkStrictly && type !== 1) {
          return
        }
        if (!rightList.value.find(m => m.id === id)) {
          rightList.value.push({ id, type, name })
        }
      } else {
        const index = rightList.value.findIndex(m => m.id === id)
        if (index !== -1) {
          rightList.value.splice(index, 1)
        }
      }
    }

    /** 选择角色 */
    const handleNodeClick = (data) => {
      const { id, type, name } = data
      if (!rightList.value.find(m => m.id === id)) {
        rightList.value.splice(0)
        rightList.value.push({ id, type, name })
      }
    }

    /** 删除已选中 */
    const remove = (e) => {
      const index = rightList.value.findIndex(m => m.id === e.id)
      if (index !== -1) {
        rightList.value.splice(index, 1)
        const n = checkedKeys.value.indexOf(e.id)
        checkedKeys.value.splice(n, 1)
        treeRef.value.setCheckedKeys(checkedKeys.value, false) // 更新选中状态
      }
    }

    /** 清空 */
    const clear = () => {
      treeRef.value.setCheckedKeys([], false)
      rightList.value.splice(0)
    }
    /** 保存 */
    const saveDialog = () => {
      visibleDialog.value = false
    }

    return {
      visibleDialog,
      treeRef,
      dialogTitle,
      filterText,
      checkedKeys,
      rightList,
      treeProps,
      filterNode,
      handleCheckChange,
      handleNodeClick,
      remove,
      clear,
      saveDialog
    }
  }
}
</script>

<style lang="scss" scoped>
  .confirm-body {
    border: 1px solid #f5f5f5;
    height: 400px;
    display: flex;

    .left {
      flex: 1;
      padding: 10px;
      border-right: 1px solid #f5f5f5;
    }

    .right {
      flex: 1;

      .right-header {
        padding: 0 20px;
        line-height: 42px;
        border-bottom: 1px solid #f5f5f5;

        a {
          text-decoration: none;
          cursor: pointer;
          color: #3296fa;
          float: right;
        }
      }

      .right-content {
        padding: 10px;
        height: 360px;
        overflow-y: auto;

        .right-content-item {
          display: flex;
          align-items: center;
          justify-content: space-between;

          .avatar {
            width: 24px;
          }
          span {
            flex: 1;
          }
        }
      }
    }
  }

  :deep(.ep-dialog__body) {
    padding: 20px;
  }
</style>
